package tum0r.server.problem.web.file_upload.filter;

import tum0r.model.ProblemInfoItem;
import tum0r.model.ProblemLevel;
import tum0r.server.problem.ProblemBase;
import tum0r.server.problem.web.file_upload.Exploit;
import tum0r.utils.shell.Shell;
import tum0r.utils.shell.ShellResult;
import tum0r.webengine.annotation.Param;
import tum0r.webengine.annotation.Server;
import tum0r.webengine.model.server.EngineFile;
import tum0r.webengine.model.server.ErrorMessage;
import tum0r.webengine.utils.server.action.Action;

import java.io.File;

/**
 * 工程: Security<br>
 * 包: tum0r.server.problem.web.file_upload.filter<br>
 * 创建者: tum0r<br>
 * 创建时间: 2021/6/26 14:02<br>
 * <br>
 */
@Server(Mapping = "/security/problem/web/file_upload/filter/compete")
public class Compete extends ProblemBase {
    public Compete() {
        information.ProblemTitle = "文件上传过滤——条件竞争";
        information.ProblemID = 14;
        information.Creator = "tum0r";
        information.ProblemLevel = ProblemLevel.MEDIUM;
        information.CreateTime = "2020/06/26";

        ProblemInfoItem problem = new ProblemInfoItem("upload", null);
        problem.addParameter("file", "File 上传的文件");
        information.ProblemInfo.add(problem);

        problem = new ProblemInfoItem("exploit", null);
        problem.addParameter("className", "String 上传的类名");
        problem.addParameter("payload", "String 命令");
        information.ProblemInfo.add(problem);
    }

    @Override
    public void description(Action<String> action) {
        action.callBack("""
                本题目上传的文件可以自定义，上传时没有类型检查，但检查到文件内容包含exp则会删除文件，那么，你能利用成功吗
                                
                最后利用的文件应是一个java文件，内容：
                public class Exp {
                    public String exploit(String payload) {
                        return payload;
                    }
                }
                """);
    }

    @Override
    public void tips(Action<String> action) {

    }

    @Override
    public void writeUp(Action<String> action) {

    }

    public void upload(@Param("file") EngineFile file, Action<String> action) throws ErrorMessage {
        action.check(file == null, "必须上传文件");
        String filePath = "upload" + File.separator + information.ProblemID + File.separator + file.getFileName();
        boolean result = file.saveFile(filePath);
        Shell shell = new Shell();
        ShellResult shellResult = shell.exec("javac " + filePath);
        if (shellResult.isSuccess()) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ignored) {
            }
            new File(filePath).delete();
            new File(filePath.replace(".java", ".class")).delete();
        }
        action.callBack(result ? "保存成功，文件路径: " + filePath : "保存失败");
    }

    public void exploit(@Param("className") String className, @Param("payload") String payload, Action<String> action) throws ErrorMessage {
        new Exploit().exp(information.ProblemID, className, payload, action);
    }
}
